//! 配置管理器 - 统一配置管理和验证
//! 
//! 基于策略模式的配置管理，支持：
//! 1. 多种配置源（文件、环境变量、命令行）
//! 2. 配置验证和校验
//! 3. 配置热重载

use crate::server::enhanced_traits::*;
use async_trait::async_trait;
use std::path::Path;
use tracing::{info, error, warn};

// =============================================================================
// 配置源抽象
// =============================================================================

/// 配置源接口 - 支持不同的配置加载方式
#[async_trait]
pub trait ConfigSource: Send + Sync {
    /// 配置源名称
    fn source_name(&self) -> &str;
    
    /// 从配置源加载配置
    async fn load_config(&self) -> Result<Box<dyn ServerConfig>, String>;
    
    /// 检查配置是否已更改
    async fn has_changed(&self) -> Result<bool, String>;
    
    /// 获取配置源详细信息
    fn source_info(&self) -> ConfigSourceInfo;
}

/// 配置源信息
#[derive(Debug, Clone)]
pub struct ConfigSourceInfo {
    pub source_type: String,
    pub location: String,
    pub last_modified: Option<std::time::SystemTime>,
    pub size: Option<u64>,
}

// =============================================================================
// 文件配置源实现
// =============================================================================

/// 文件配置源 - 从配置文件加载
pub struct FileConfigSource {
    file_path: String,
    config_format: ConfigFormat,
    last_modified: Option<std::time::SystemTime>,
}

/// 配置文件格式
#[derive(Debug, Clone)]
pub enum ConfigFormat {
    Toml,
    Json,
    Yaml,
    Auto, // 自动检测
}

impl FileConfigSource {
    pub fn new(file_path: String, format: ConfigFormat) -> Self {
        Self {
            file_path,
            config_format: format,
            last_modified: None,
        }
    }
    
    /// 自动检测格式的构造函数
    pub fn auto(file_path: String) -> Self {
        Self::new(file_path, ConfigFormat::Auto)
    }
    
    /// 检测配置文件格式
    fn detect_format(&self) -> ConfigFormat {
        match self.config_format {
            ConfigFormat::Auto => {
                if self.file_path.ends_with(".toml") {
                    ConfigFormat::Toml
                } else if self.file_path.ends_with(".json") {
                    ConfigFormat::Json
                } else if self.file_path.ends_with(".yaml") || self.file_path.ends_with(".yml") {
                    ConfigFormat::Yaml
                } else {
                    ConfigFormat::Toml // 默认
                }
            }
            _ => self.config_format.clone(),
        }
    }
    
    /// 获取文件元数据
    fn get_file_metadata(&self) -> Result<std::fs::Metadata, String> {
        std::fs::metadata(&self.file_path)
            .map_err(|e| format!("无法获取文件元数据: {} - {}", self.file_path, e))
    }
}

#[async_trait]
impl ConfigSource for FileConfigSource {
    fn source_name(&self) -> &str {
        "FileConfigSource"
    }
    
    async fn load_config(&self) -> Result<Box<dyn ServerConfig>, String> {
        info!("从文件加载配置: {}", self.file_path);
        
        // 检查文件是否存在
        if !Path::new(&self.file_path).exists() {
            return Err(format!("配置文件不存在: {}", self.file_path));
        }
        
        let format = self.detect_format();
        info!("检测到配置格式: {:?}", format);
        
        match format {
            ConfigFormat::Toml => self.load_toml_config().await,
            ConfigFormat::Json => self.load_json_config().await,
            ConfigFormat::Yaml => self.load_yaml_config().await,
            ConfigFormat::Auto => unreachable!(), // 已经在detect_format中处理
        }
    }
    
    async fn has_changed(&self) -> Result<bool, String> {
        let metadata = self.get_file_metadata()?;
        let current_modified = metadata.modified()
            .map_err(|e| format!("无法获取文件修改时间: {}", e))?;
        
        match self.last_modified {
            Some(last) => Ok(current_modified > last),
            None => Ok(true), // 首次检查认为已更改
        }
    }
    
    fn source_info(&self) -> ConfigSourceInfo {
        let metadata = self.get_file_metadata().ok();
        
        ConfigSourceInfo {
            source_type: "File".to_string(),
            location: self.file_path.clone(),
            last_modified: metadata.as_ref().and_then(|m| m.modified().ok()),
            size: metadata.as_ref().map(|m| m.len()),
        }
    }
}

impl FileConfigSource {
    /// 加载TOML配置
    async fn load_toml_config(&self) -> Result<Box<dyn ServerConfig>, String> {
        use crate::config::TomlConfigParser;
        use crate::config::ConfigLoader;
        
        let parser = TomlConfigParser;
        let cluster_config = parser.load_from_file(Path::new(&self.file_path))
            .map_err(|e| format!("加载TOML配置失败: {}", e))?;
        
        // 根据集群配置创建ServerConfig
        let server_config = ClusterConfig {
            bind_address: cluster_config.redis_addr(),
            cluster_config,
        };
        
        Ok(Box::new(server_config))
    }
    
    /// 加载JSON配置
    async fn load_json_config(&self) -> Result<Box<dyn ServerConfig>, String> {
        // TODO: 实现JSON配置加载
        Err("JSON配置格式暂未实现".to_string())
    }
    
    /// 加载YAML配置
    async fn load_yaml_config(&self) -> Result<Box<dyn ServerConfig>, String> {
        // TODO: 实现YAML配置加载
        Err("YAML配置格式暂未实现".to_string())
    }
}

// =============================================================================
// 环境变量配置源
// =============================================================================

/// 环境变量配置源
pub struct EnvConfigSource {
    prefix: String,
}

impl EnvConfigSource {
    pub fn new(prefix: String) -> Self {
        Self { prefix }
    }
    
    pub fn redis_rs2() -> Self {
        Self::new("REDIS_RS2".to_string())
    }
}

#[async_trait]
impl ConfigSource for EnvConfigSource {
    fn source_name(&self) -> &str {
        "EnvConfigSource"
    }
    
    async fn load_config(&self) -> Result<Box<dyn ServerConfig>, String> {
        info!("从环境变量加载配置，前缀: {}", self.prefix);
        
        // 读取基本配置
        let bind_address = std::env::var(format!("{}_BIND_ADDRESS", self.prefix))
            .unwrap_or_else(|_| "127.0.0.1:6379".to_string());
        
        let mode = std::env::var(format!("{}_MODE", self.prefix))
            .unwrap_or_else(|_| "standalone".to_string());
        
        match mode.to_lowercase().as_str() {
            "standalone" => {
                let config = StandaloneConfig { bind_address };
                Ok(Box::new(config))
            }
            "cluster" => {
                // 创建默认集群配置
                let cluster_config = self.create_cluster_config_from_env(&bind_address)?;
                let config = ClusterConfig {
                    bind_address,
                    cluster_config,
                };
                Ok(Box::new(config))
            }
            _ => Err(format!("不支持的服务器模式: {}", mode)),
        }
    }
    
    async fn has_changed(&self) -> Result<bool, String> {
        // 环境变量在程序运行期间通常不会改变
        // 这里可以实现更复杂的检查逻辑
        Ok(false)
    }
    
    fn source_info(&self) -> ConfigSourceInfo {
        ConfigSourceInfo {
            source_type: "Environment".to_string(),
            location: format!("环境变量前缀: {}", self.prefix),
            last_modified: None,
            size: None,
        }
    }
}

impl EnvConfigSource {
    /// 从环境变量创建集群配置
    fn create_cluster_config_from_env(&self, _bind_address: &str) -> Result<crate::cluster::ClusterConfig, String> {
        let node_id = std::env::var(format!("{}_NODE_ID", self.prefix))
            .unwrap_or_else(|_| uuid::Uuid::new_v4().to_string());
        
        let redis_port = std::env::var(format!("{}_REDIS_PORT", self.prefix))
            .unwrap_or_else(|_| "7001".to_string())
            .parse::<u16>()
            .map_err(|e| format!("无效的Redis端口: {}", e))?;
        
        let cluster_port = std::env::var(format!("{}_CLUSTER_PORT", self.prefix))
            .unwrap_or_else(|_| "17001".to_string())
            .parse::<u16>()
            .map_err(|e| format!("无效的集群端口: {}", e))?;
        
        let seeds = std::env::var(format!("{}_SEEDS", self.prefix))
            .unwrap_or_else(|_| String::new())
            .split(',')
            .filter(|s| !s.trim().is_empty())
            .map(|s| s.trim().to_string())
            .collect();
        
        let config = crate::cluster::ClusterConfig::default()
            .with_node_id(node_id)
            .with_bind_addr("127.0.0.1")
            .with_redis_port(redis_port)
            .with_cluster_port(cluster_port)
            .with_seeds(seeds);
        
        config.validate()
            .map_err(|e| format!("集群配置验证失败: {}", e))?;
        
        Ok(config)
    }
}

// =============================================================================
// 命令行配置源
// =============================================================================

/// 命令行参数配置源
pub struct CliConfigSource {
    args: Vec<String>,
}

impl CliConfigSource {
    pub fn new(args: Vec<String>) -> Self {
        Self { args }
    }
    
    pub fn from_env() -> Self {
        Self::new(std::env::args().collect())
    }
}

#[async_trait]
impl ConfigSource for CliConfigSource {
    fn source_name(&self) -> &str {
        "CliConfigSource"
    }
    
    async fn load_config(&self) -> Result<Box<dyn ServerConfig>, String> {
        info!("从命令行参数加载配置");
        
        // 简单的命令行解析（实际项目中可以使用clap等库）
        let mut bind_address = "127.0.0.1:6379".to_string();
        let mut mode = "standalone".to_string();
        
        for i in 0..self.args.len() {
            match self.args[i].as_str() {
                "--bind" | "-b" => {
                    if i + 1 < self.args.len() {
                        bind_address = self.args[i + 1].clone();
                    }
                }
                "--mode" | "-m" => {
                    if i + 1 < self.args.len() {
                        mode = self.args[i + 1].clone();
                    }
                }
                _ => {}
            }
        }
        
        match mode.to_lowercase().as_str() {
            "standalone" => {
                let config = StandaloneConfig { bind_address };
                Ok(Box::new(config))
            }
            "cluster" => {
                // 对于集群模式，命令行参数通常不够，应该结合其他配置源
                Err("集群模式需要完整的配置文件，命令行参数不足".to_string())
            }
            _ => Err(format!("不支持的服务器模式: {}", mode)),
        }
    }
    
    async fn has_changed(&self) -> Result<bool, String> {
        // 命令行参数在程序运行期间不会改变
        Ok(false)
    }
    
    fn source_info(&self) -> ConfigSourceInfo {
        ConfigSourceInfo {
            source_type: "CommandLine".to_string(),
            location: format!("命令行参数: {}", self.args.join(" ")),
            last_modified: None,
            size: None,
        }
    }
}

// =============================================================================
// 统一配置管理器
// =============================================================================

/// 配置管理器 - 统一管理多个配置源
pub struct ConfigManager {
    /// 配置源列表（按优先级排序）
    config_sources: Vec<Box<dyn ConfigSource>>,
    
    /// 当前配置
    current_config: Option<Box<dyn ServerConfig>>,
    
    /// 配置热重载间隔
    reload_interval: std::time::Duration,
    
    /// 是否启用热重载
    hot_reload_enabled: bool,
}

impl ConfigManager {
    /// 创建新的配置管理器
    pub fn new() -> Self {
        Self {
            config_sources: Vec::new(),
            current_config: None,
            reload_interval: std::time::Duration::from_secs(60), // 默认60秒检查一次
            hot_reload_enabled: false,
        }
    }
    
    /// 添加配置源（优先级从高到低）
    pub fn add_source(&mut self, source: Box<dyn ConfigSource>) {
        info!("添加配置源: {}", source.source_name());
        self.config_sources.push(source);
    }
    
    /// 设置热重载间隔
    pub fn set_reload_interval(&mut self, interval: std::time::Duration) {
        self.reload_interval = interval;
    }
    
    /// 启用热重载
    pub fn enable_hot_reload(&mut self) {
        self.hot_reload_enabled = true;
        info!("启用配置热重载，检查间隔: {:?}", self.reload_interval);
    }
    
    /// 禁用热重载
    pub fn disable_hot_reload(&mut self) {
        self.hot_reload_enabled = false;
        info!("禁用配置热重载");
    }
    
    /// 加载配置
    pub async fn load_config(&mut self) -> Result<Box<dyn ServerConfig>, String> {
        info!("开始加载配置，共{}个配置源", self.config_sources.len());
        
        let mut errors = Vec::new();
        
        // 按优先级尝试加载配置
        for (index, source) in self.config_sources.iter().enumerate() {
            info!("尝试配置源 {}: {}", index + 1, source.source_name());
            
            match source.load_config().await {
                Ok(config) => {
                    info!("✅ 配置加载成功，使用配置源: {}", source.source_name());
                    
                    // 验证配置
                    if let Err(e) = config.validate() {
                        warn!("配置验证失败: {} - {}", source.source_name(), e);
                        errors.push(format!("{}: 验证失败 - {}", source.source_name(), e));
                        continue;
                    }
                    
                    self.current_config = Some(config.clone_config());
                    return Ok(config);
                }
                Err(e) => {
                    warn!("配置源加载失败: {} - {}", source.source_name(), e);
                    errors.push(format!("{}: {}", source.source_name(), e));
                }
            }
        }
        
        let error_msg = format!("所有配置源加载失败: {}", errors.join("; "));
        error!("{}", error_msg);
        Err(error_msg)
    }
    
    /// 重新加载配置
    pub async fn reload_config(&mut self) -> Result<Box<dyn ServerConfig>, String> {
        info!("重新加载配置");
        self.load_config().await
    }
    
    /// 检查配置是否需要重新加载
    pub async fn check_for_changes(&self) -> Result<bool, String> {
        if !self.hot_reload_enabled {
            return Ok(false);
        }
        
        for source in &self.config_sources {
            match source.has_changed().await {
                Ok(true) => {
                    info!("检测到配置源变更: {}", source.source_name());
                    return Ok(true);
                }
                Ok(false) => {
                    // 继续检查下一个配置源
                }
                Err(e) => {
                    warn!("检查配置源变更失败: {} - {}", source.source_name(), e);
                }
            }
        }
        
        Ok(false)
    }
    
    /// 获取当前配置
    pub fn current_config(&self) -> Option<&dyn ServerConfig> {
        self.current_config.as_ref().map(|c| c.as_ref())
    }
    
    /// 获取配置源信息
    pub fn source_info(&self) -> Vec<ConfigSourceInfo> {
        self.config_sources.iter().map(|s| s.source_info()).collect()
    }
    
    /// 启动热重载监控
    pub async fn start_hot_reload_monitor(&self) -> tokio::task::JoinHandle<()> {
        if !self.hot_reload_enabled {
            warn!("热重载未启用，监控任务将立即退出");
        }
        
        let interval = self.reload_interval;
        let enabled = self.hot_reload_enabled;
        
        tokio::spawn(async move {
            if !enabled {
                return;
            }
            
            let mut interval_timer = tokio::time::interval(interval);
            
            loop {
                interval_timer.tick().await;
                
                // 注意：这里需要访问ConfigManager实例来检查变更
                // 在实际实现中，应该使用Arc<Mutex<ConfigManager>>或类似的并发安全结构
                info!("执行配置热重载检查");
                
                // TODO: 实现实际的变更检查和重载逻辑
            }
        })
    }
}

impl Default for ConfigManager {
    fn default() -> Self {
        Self::new()
    }
}

// =============================================================================
// 便利构造函数
// =============================================================================

/// 创建标准配置管理器（文件 > 环境变量 > 命令行）
pub fn create_standard_config_manager() -> ConfigManager {
    let mut manager = ConfigManager::new();
    
    // 按优先级添加配置源
    manager.add_source(Box::new(CliConfigSource::from_env())); // 最高优先级
    manager.add_source(Box::new(EnvConfigSource::redis_rs2()));
    // 文件配置源需要在知道文件路径时添加
    
    manager
}

/// 创建带文件配置的管理器
pub fn create_file_config_manager(config_file: String) -> ConfigManager {
    let mut manager = create_standard_config_manager();
    
    // 文件配置源优先级最低
    manager.add_source(Box::new(FileConfigSource::auto(config_file)));
    
    manager
}

/// 创建生产环境配置管理器
pub fn create_production_config_manager(config_file: String) -> ConfigManager {
    let mut manager = create_file_config_manager(config_file);
    
    // 启用热重载
    manager.enable_hot_reload();
    manager.set_reload_interval(std::time::Duration::from_secs(30));
    
    manager
}